﻿using System;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;

namespace FluentTemplates
{
    public static class TemplatePartBinding
    {
        public static void BindTemplateParts<T>(T control) where T : Control, ITemplatePartBinding
        {
            var t = typeof(T);
            var itemplatePart = control as ITemplatePartBinding;
            if (itemplatePart==null)
                throw new ArgumentException("Control must implement ITemplatePartBinding");

            BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;


            var properties =
                t.GetProperties(flags).OfType<MemberInfo>()
                    .ToList()
                    .Where(x => x.GetCustomAttributes(typeof(TemplatePartBindingAttribute), true).Count() == 1);

            var fields =
                t.GetFields(flags).OfType<MemberInfo>()
                    .ToList()
                    .Where(x => x.GetCustomAttributes(typeof(TemplatePartBindingAttribute), true).Count() == 1);

            var propertiesAndFields = properties.Union(fields);
            foreach (var property in propertiesAndFields)
            {
                var template =
                    property.GetCustomAttributes(typeof(TemplatePartBindingAttribute), true).FirstOrDefault() as TemplatePartBindingAttribute;

                if (template == null) continue;

                var obj = itemplatePart.GetTemplatePartBinding(template.Name);
                if (obj == null && template.Required && !DesignTools.IsInDesignModeStatic)
                    throw new ArgumentException(string.Format("{0} is required", template.Name));

                if (property is PropertyInfo)
                    ((PropertyInfo)property).SetValue(control, obj, null);
                else if (property is FieldInfo)
                {
                       
                    ((FieldInfo)property).SetValue(control, obj);
                }

                //if (!string.IsNullOrEmpty(template.Callback) && !DesignTools.IsInDesignModeStatic)
                //{
                //    try { ControlExtensions.RunInstanceMethod(typeof(Control), template.Callback, control, null); }
                //    catch
                //    {
                //    }
                //}
            }

        }
    }

    public interface ITemplatePartBinding
    {
        object GetTemplatePartBinding(string partName);
        //TemplatePart<T> GetTemplatePartBinding<T>(string partName) where T: DependencyObject;
    }
}